// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: jing， gekim

#pragma once

#include <map>
#include <string>
#include <vector>

#include "coin2/exchange/base/feed/processor.h"

namespace coin2::exchange::coinone::feed_v2 {
namespace impl {

class CoinoneUnitMap {
 public:
  using UnitMapT = std::map<std::string, std::string>;

 public:
  CoinoneUnitMap() {
    std::ifstream ifs("data/coin2/feed/coinone_unit_map.json");
    nlohmann::json jf = nlohmann::json::parse(ifs);
    auto jf_unit_map = jf.find("feed")
                           ->find("exchanges")
                           ->find("Spot.Coinone.v2")
                           ->find("unit_map");
    unit_map_ = jf_unit_map->get<UnitMapT>();
  }

  // Use copy for multithread
  UnitMapT GetUnitMap() { return unit_map_; }

 private:
  UnitMapT unit_map_;
};

static CoinoneUnitMap coinone_unit_map;

class CoinoneRequestGenerator : public base::feed::RequestGenerator {
 public:
  std::vector<std::string> GenerateRequests(
      const std::vector<std::string>& channels,
      const std::vector<std::string>& symbols,
      const std::map<std::string, std::string>& channel_templates,
      const std::string& request_template) override {
    // {channel} and {json_list}
    std::vector<std::string> reqs;

    auto unit_map = coinone_unit_map.GetUnitMap();

    // {num products} * {num channel types}
    for (auto& channel : channels) {
      for (auto& symbol : symbols) {
        std::string c = channel_templates.at(channel);
        boost::replace_all(c, "{}", symbol);
        auto unit_it = unit_map.find(symbol);
        if (unit_it == unit_map.end()) {
          THROW() << "[Coinone Request Generator] unrecognized product: "
                  << symbol;
        }
        boost::replace_all(c, "{unit}", unit_it->second);

        std::string s = request_template;
        boost::replace_all(s, "{channel}", c);
        reqs.push_back(s);
      }
    }
    return reqs;
  }
};

}  // namespace impl
using impl::CoinoneRequestGenerator;
}  // namespace coin2::exchange::coinone::feed_v2
